#include<iostream>
#include<string>
#include<memory>

using namespace std;


//定义一个电脑类
class Computer
{
public:
    Computer(){}
    void SetBoard(const string& board)
    {
        _board=board;
    }

    void SetDisp(const string& Disp)
    {
        _dispaly=Disp;
    }
    void Print()
    {
        cout<<"board:"<<_board<<" _display:"<<_dispaly<<" _os:"<<_os<<endl;
    }
    virtual void SetOs(const string& os)=0;
protected:
    string _board;
    string _dispaly;
    string _os;
};
/*
继承的内存布局‌：
当派生类继承基类时，基类的成员变量会被完整地包含在派生类对象的内存布局中。
这意味着派生类对象内部天然就包含了一个完整的基类子对象。

‌作用域规则‌：
在派生类的成员函数（包括重写的虚函数）中，编译器会按照名称查找规则搜索标识符：

先在当前类作用域查找
然后在基类作用域查找
最后在外围命名空间查找
‌this指针的隐式转换‌：
当通过派生类对象调用重写的虚函数时，
编译器会自动将派生类指针/引用转换为基类指针/引用（向上转型），
这使得在函数体内可以自然地访问基类成员。

‌虚函数调用机制‌：
即使函数被重写，通过虚表调用时，函数仍然是在派生类对象的上下文中执行，
而这个对象包含完整的基类子对象。

通过基类指针是不能访问派生类的成员函数和变量的除法通过继承虚函重写方法
基类指针访问被重写的虚函数从而访问派生类的成员
*/
class MacBook:public Computer
{
public:
    MacBook(){}
    //通过派生类指针是可以访问继承的基类的成员变量和 函数的
    void SetOs(const string& os)override
    {
        _os=os;
    }

};

//再定义一个Builder抽象类提供建造电脑零件方法
class Builder
{
public:
    Builder(){}
    virtual void BuildBoard(const string& board)=0;//建造主板
    virtual void BuildDisp(const string& disp)=0;//建造显示器
    virtual void BuildOs()=0;
    virtual shared_ptr<Computer> build()=0;
};

//定义具体类型的电脑生产类继承生产方法来生产零部件
class MacBookBuilder:public Builder
{
public:
    MacBookBuilder():_computer(make_shared<MacBook>())//定义具体的派生类指针用基类指针接收
    {}
    void BuildBoard(const string& board) override//建造主板
    {
        _computer->SetBoard(board);
    }
    void BuildDisp(const string& disp) override//建造显示器
    {
        _computer->SetDisp(disp);
    }
    void BuildOs()override
    {
        _computer->SetOs("xx.1.1.12");
    }

    //返回一台电脑
    shared_ptr<Computer> build() override
    {
        return _computer;
    }
private:
    shared_ptr<Computer> _computer;//定义电脑基类指针引用 
};

//再定义一个管理者去控制构造一台电脑的顺序
class Director
{
public:
    Director(Builder* build):_build(build)
    {}
    void Construct(const string& board,const string& disp)
    {
        _build->BuildBoard(board);
        _build->BuildDisp(disp);
        _build->BuildOs();
    }
private:
    shared_ptr<Builder> _build;
};


int main()
{
    //1 定义具体电脑的生产者对象
    Builder* build=new MacBookBuilder();

    //2 定义构造者，按照具体顺序构造一台电脑
    unique_ptr<Director> dir=make_unique<Director>(build);
    dir->Construct("华硕","三星");
    shared_ptr<Computer> Mac=build->build();
    Mac->Print();
    //delete build;
    return 0;
}